package ua.dp.mzav.train.tm.model;

/**
 * This class represents a Domain Model entity according to NFR2.1 with ability
 * to manage Employee's data.
 */
public class Employee extends EmployeeReadable
{

    static final int INITIAL_HR_ID = -1;
    
    private static final long serialVersionUID = 1L;

    Employee()
    {
    }
    
    /// @name Person data modifiers.
    ///@{
    /**
     * Defines Title of the Employee, for instance Mr. or Ms.
     *
     * @param[in] aTitle New Title. null indicates "not defined", empty string -
     * this info is not used for Person naming.
     * @see EmployeeReadable#getTitle()
     */
    public final void setTitle(final String aTitle)
    {
        title = aTitle;
    }

    /**
     * Defines First name of the Employee.
     *
     * @param[in] aName New First name. null indicates "not defined", empty
     * string - this info is not used for Person naming.
     * @see EmployeeReadable#getFirstName()
     */
    public final void setFirstName(final String aName)
    {
        firstName = aName;
    }

    /**
     * Defines Middle name of the Employee.
     *
     * @param[in] aName New Middle name. null indicates "not defined", empty
     * string - this info is not used for Person naming.
     * @see EmployeeReadable#getMiddleName()
     */
    public final void setMiddleName(final String aName)
    {
        middleName = aName;
    }

    /**
     * Defines Last name of the Employee.
     *
     * @param[in] aName New Last name. null indicates "not defined", empty
     * string - this info is not used for Person naming.
     * @see EmployeeReadable#getLastName()
     */
    public final void setLastName(final String aName)
    {
        lastName = aName;
    }

    ///@}
    /**
     * Supervisor of the employer - according to NFR1.4
     *
     * @return Supervisor. Can not refer itself. Can not refer Manager. @retval
     * null If Supervisor has not been assigned.
     * @see Employee#setSupervisor
     */
    @Override
    public final Employee getSupervisor()
    {
        return supervisor;
    }

    /**
     * Function (re)assigns a Supervisor to this Employee.
     *
     * @param[in] aSupervisor - (new) Supervisor. null to indicate that
     * Supervisor is not defined for the Employee. If supervisor is equal to
     * Manager - the same result as when null specified.
     * @see Employee#getSupervisor
     */
    public final void setSupervisor(final Employee aSupervisor)
    {
        if (aSupervisor == null)
        {
            supervisor = null;
        }
        else
        {
            if (aSupervisor.equals(this))
            {
                throw new IllegalArgumentException("Supervisor for yourself");
            }
            supervisor = aSupervisor.equals(manager) ? null : aSupervisor;
        }
    }

    /**
     * Manager of the employer - according to NFR1.2
     *
     * @return Manager. Can not refer itself. @retval null If the Employee is
     * Top-Manager NFR2.3
     * @see Employee#setManager
     */
    @Override
    public final Employee getManager()
    {
        return manager;
    }

    /**
     * Function (re)assigns a Manager to this Employee.
     *
     * @param[in] aManager - (new) Manager. null to indicate that Manager is not
     * defined for the Employee. It is for Top Manager only.
     * @see Employee#getManager @post getSupervisor() == null if aManager was
     * initially Supervisor.
     */
    public final void setManager(final Employee aManager)
    {
        if (aManager == null)
        {
            manager = null;
        }
        else
        {
            if (aManager.equals(this))
            {
                throw new IllegalArgumentException("Employee can not be Manager for yourself");
            }
            manager = aManager;
            if (manager.equals(supervisor))
            {
                supervisor = null;
            }
        }
    }
}
